package com.jar.exercise.多线程.线程回调;

import org.junit.Test;

import java.util.concurrent.*;

/**
 * Callable 接口实现 用于回调得到其他线程的结果
 * 此类主要是原始FutureTask 和 CompletableFuture 类进行对比
 */
public class CompletableFutureAndFutureTaskDemo {
    /**
     * 1、传统方式使用FutureTask
     */
    @Test
    public void test1() throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(() -> {
            for (int i = 0; i < 10; i++) {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + "::" + i);
            }
            return "完成";
        });
        new Thread(futureTask).start();
        String s = futureTask.get();
        System.out.println(s);
    }

    /**
     * 线程池方式使用FutureTask
     * FutureTask 调用get方法会阻塞，isDone方法使用也不够优雅
     */
    @Test
    public void test2() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<String> future = executorService.submit(() -> {
            System.out.println(Thread.currentThread().getName() + "===>正在执行");
            Thread.sleep(3000);
            return "success";
        });
        if (future.isDone()) {
            System.out.println("异步任务结束，结果：" + future.get());
        } else {
            System.out.println("异步任务还未结束，请稍后再试");
        }
    }

    /**
     * 使用CompletableFuture(jdk1.8提供)
     * 和上面效果一样都是阻塞，异步请看test4方法
     */
    @Test
    public void test3() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("=============>异步线程开始...");
            System.out.println("=============>异步线程为：" + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("=============>异步线程结束...");
            return "supplierResult";
        });
        // 阻塞获取结果
        System.out.println("异步结果是:" + completableFuture.get());
        System.out.println("main结束");
    }

    @Test
    public void test4() {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("=============>异步线程开始...");
            System.out.println("=============>异步线程为：" + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("=============>异步线程结束...");
            return "supplierResult";
        });

        // 异步回调：上面的Supplier#get()返回结果后，异步线程会回调BiConsumer#accept()
        completableFuture
                .whenComplete((s, throwable) -> {
                    System.out.println("=============>异步任务结束回调...result:" + s);
                    System.out.println("=============>回调线程为：" + Thread.currentThread().getName());
                    System.out.println("throwable" + throwable.getMessage());
                })
                .exceptionally(Throwable::getMessage);


        // CompletableFuture的异步线程是守护线程，一旦main结束就没了，为了看到打印结果，需要让main休眠一会儿
//        while (Thread.activeCount() > 1) {
//            Thread.yield();
//        }
    }


}


